#pragma once

#include "stdafx.h"

using namespace std;

TNode::TNode()
{
	_next=0;
	_prev=0;
	_parent=0;
	_childH=0;
	_childT=0;
	_nbchildren=0;
	_object = "";
};
TNode::TNode(const char* obj, TNode* parent)
{
	_next=0;
	_prev=0;
	_parent=0;
	_childH=0;
	_childT=0;
	_nbchildren=0;
	_object = obj;
	if (parent != 0){SetParent(parent);};
};


TNode* TNode::Copy(TNode*Parent)
{
	TNode* node = new TNode(_object.c_str(),Parent);
	
	TNode* child = _childH;
	while (child!=0)
	{
		child->Copy(node);
		child=child->_next;
	};
	return node;
};

void TNode::Delete()
{
	UnLink();
	_DeleteSub();
	delete this;
};

void TNode::_DeleteSub()
{
	TNode* node=_childH;
	TNode* node_=_childH;

	while (node !=0)
	{
		node_ = node; node = node->_next;
		node_->_DeleteSub();
		delete node_;
	};
};


TNode* TNode::Get(int id)
{
	if (id>_nbchildren){return 0;};
	if (id<1){return 0;};

	TNode*node = _childH;
	int iter=0;
	for (iter=1;iter<id;iter++)
	{
		node=node->_next;
	};
	return node;
};

TNode* TNode::Find(const char* obj)
{
	if (_object.compare(obj)==0) return this;
	
	TNode* child = _childH;
	while (child != 0)
	{
		TNode * subchild = child->Find(obj);
		if (subchild != 0) {return subchild;};

		child=child->_next;
	};
	return 0;
};

// Unlink from parent
void TNode::UnLink()
{
	if (_parent != 0)
	{
		_parent->_nbchildren -= 1;

		if (this==_parent->_childH)
		{
			if (this==_parent->_childT)
			{
				_parent->_childH = 0;
				_parent->_childT = 0;
			}
			else
			{
				_parent->_childH = _parent->_childH->_next;
			};
		}
		else
		{
			if (this==_parent->_childT)
			{
				_parent->_childT=_parent->_childT->_prev;
				_parent->_childT->_next=0;
			}
			else
			{
				_next->_prev = _prev;
				_prev->_next = _next;
			};
		};
	};
	_next=0;
	_prev=0;
};

int TNode::SetParent(TNode* parent)
{
	if (parent==_parent){return 1;};
	
	// Check illegal recursive parent or "self-parenting"
	TNode* n = parent;
	while(n!=0)
	{
		if (n == this) return 0;
		n=n->_parent;
	};
	
	// Unlink from previous parent
	this->UnLink();
	
	// Link to new parent
	if (parent != 0)
	{
		_parent=parent;
		parent->_nbchildren++;
		
		if (parent->_childH == 0)
		{
			parent->_childH = this;
			parent->_childT = this;
			_prev = 0;
			_next = 0;
		}
		else
		{
			parent->_childT->_next=this;
			_prev = parent->_childT;
			_next = 0;
			parent->_childT = this;
		};
	}
	else
	{
		_next=0;
		_prev=0;
		_parent=0;
	};

	return 1;
;};
